import * as vscode from 'vscode';
import * as path from 'path';

export interface UnitTestPreviewData {
    /** 生成的测试代码 */
    testCode: string;
    /** 测试文件路径 */
    testFilePath: string;
    /** 源文件路径 */
    sourceFilePath: string;
    /** 函数名 */
    functionName: string;
    /** 生成说明 */
    explanation: string;
    /** GN文件变更 */
    gnChanges?: {
        filePath: string;
        oldContent: string;
        newContent: string;
        diff: string;
    };
}

/**
 * 单元测试预览面板
 * 显示生成的测试代码、说明和GN文件变更，允许用户预览和确认
 */
export class UnitTestPreviewPanel {
    public static currentPanel: UnitTestPreviewPanel | undefined;
    private readonly _panel: vscode.WebviewPanel;
    private readonly _extensionUri: vscode.Uri;
    private _disposables: vscode.Disposable[] = [];
    private _onAcceptCallback?: (data: UnitTestPreviewData) => void;
    private _onRejectCallback?: () => void;
    private _previewData?: UnitTestPreviewData;

    private constructor(panel: vscode.WebviewPanel, extensionUri: vscode.Uri) {
        this._panel = panel;
        this._extensionUri = extensionUri;

        // 设置webview内容
        this._panel.webview.html = this._getHtmlForWebview();

        // 监听消息
        this._panel.webview.onDidReceiveMessage(
            message => {
                switch (message.command) {
                    case 'accept':
                        if (this._onAcceptCallback && this._previewData) {
                            this._onAcceptCallback(this._previewData);
                        }
                        this._panel.dispose();
                        return;
                    case 'reject':
                        if (this._onRejectCallback) {
                            this._onRejectCallback();
                        }
                        this._panel.dispose();
                        return;
                    case 'copyCode':
                        vscode.env.clipboard.writeText(message.code);
                        vscode.window.showInformationMessage('测试代码已复制到剪贴板');
                        return;
                }
            },
            null,
            this._disposables
        );

        // 面板关闭时清理资源
        this._panel.onDidDispose(() => this.dispose(), null, this._disposables);
    }

    /**
     * 创建或显示预览面板
     */
    public static createOrShow(
        extensionUri: vscode.Uri,
        data: UnitTestPreviewData,
        onAccept: (data: UnitTestPreviewData) => void,
        onReject: () => void
    ): UnitTestPreviewPanel {
        const column = vscode.ViewColumn.One;

        // 如果已经存在面板，显示它
        if (UnitTestPreviewPanel.currentPanel) {
            UnitTestPreviewPanel.currentPanel._panel.reveal(column);
            UnitTestPreviewPanel.currentPanel.update(data, onAccept, onReject);
            return UnitTestPreviewPanel.currentPanel;
        }

        // 否则，创建新的面板
        const panel = vscode.window.createWebviewPanel(
            'unitTestPreview',
            '单元测试预览',
            column,
            {
                enableScripts: true,
                retainContextWhenHidden: true,
                localResourceRoots: [extensionUri]
            }
        );

        UnitTestPreviewPanel.currentPanel = new UnitTestPreviewPanel(panel, extensionUri);
        UnitTestPreviewPanel.currentPanel.update(data, onAccept, onReject);
        return UnitTestPreviewPanel.currentPanel;
    }

    /**
     * 更新预览数据
     */
    public update(
        data: UnitTestPreviewData,
        onAccept: (data: UnitTestPreviewData) => void,
        onReject: () => void
    ): void {
        this._previewData = data;
        this._onAcceptCallback = onAccept;
        this._onRejectCallback = onReject;
        
        // 发送数据到webview
        this._panel.webview.postMessage({
            command: 'updatePreview',
            data: data
        });
    }

    public dispose(): void {
        UnitTestPreviewPanel.currentPanel = undefined;

        this._panel.dispose();

        while (this._disposables.length) {
            const disposable = this._disposables.pop();
            if (disposable) {
                disposable.dispose();
            }
        }
    }

    private _getHtmlForWebview(): string {
        return `<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>单元测试预览</title>
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }
        
        body {
            font-family: var(--vscode-font-family);
            color: var(--vscode-foreground);
            background-color: var(--vscode-editor-background);
            padding: 20px;
            line-height: 1.6;
        }
        
        .container {
            max-width: 1200px;
            margin: 0 auto;
        }
        
        h1 {
            color: var(--vscode-titleBar-activeForeground);
            margin-bottom: 20px;
            font-size: 24px;
            border-bottom: 2px solid var(--vscode-panel-border);
            padding-bottom: 10px;
        }
        
        .section {
            margin-bottom: 30px;
            background-color: var(--vscode-editor-background);
            border: 1px solid var(--vscode-panel-border);
            border-radius: 6px;
            overflow: hidden;
        }
        
        .section-header {
            background-color: var(--vscode-titleBar-activeBackground);
            color: var(--vscode-titleBar-activeForeground);
            padding: 12px 16px;
            font-weight: 600;
            font-size: 16px;
            display: flex;
            justify-content: space-between;
            align-items: center;
        }
        
        .section-content {
            padding: 16px;
        }
        
        .info-grid {
            display: grid;
            grid-template-columns: 120px 1fr;
            gap: 12px;
            margin-bottom: 16px;
        }
        
        .info-label {
            color: var(--vscode-descriptionForeground);
            font-weight: 500;
        }
        
        .info-value {
            color: var(--vscode-foreground);
            word-break: break-all;
        }
        
        .code-block {
            background-color: var(--vscode-textCodeBlock-background);
            border: 1px solid var(--vscode-panel-border);
            border-radius: 4px;
            padding: 12px;
            margin-top: 12px;
            overflow-x: auto;
            position: relative;
        }
        
        .code-block pre {
            margin: 0;
            font-family: var(--vscode-editor-font-family);
            font-size: var(--vscode-editor-font-size);
            line-height: 1.5;
            white-space: pre-wrap;
            word-wrap: break-word;
        }
        
        .explanation {
            color: var(--vscode-descriptionForeground);
            line-height: 1.8;
            padding: 12px;
            background-color: var(--vscode-textBlockQuote-background);
            border-left: 4px solid var(--vscode-textLink-foreground);
            border-radius: 4px;
        }
        
        .diff-view {
            display: grid;
            grid-template-columns: 1fr 1fr;
            gap: 12px;
            margin-top: 12px;
        }
        
        .diff-column h4 {
            color: var(--vscode-titleBar-activeForeground);
            margin-bottom: 8px;
            font-size: 14px;
        }
        
        .diff-added {
            background-color: rgba(0, 255, 0, 0.1);
            border-left: 3px solid #00ff00;
        }
        
        .diff-removed {
            background-color: rgba(255, 0, 0, 0.1);
            border-left: 3px solid #ff0000;
        }
        
        .button-group {
            display: flex;
            gap: 12px;
            justify-content: flex-end;
            margin-top: 30px;
            padding-top: 20px;
            border-top: 1px solid var(--vscode-panel-border);
        }
        
        button {
            padding: 10px 24px;
            font-size: 14px;
            font-weight: 500;
            border: none;
            border-radius: 4px;
            cursor: pointer;
            transition: all 0.2s;
        }
        
        .btn-primary {
            background-color: var(--vscode-button-background);
            color: var(--vscode-button-foreground);
        }
        
        .btn-primary:hover {
            background-color: var(--vscode-button-hoverBackground);
        }
        
        .btn-secondary {
            background-color: var(--vscode-button-secondaryBackground);
            color: var(--vscode-button-secondaryForeground);
        }
        
        .btn-secondary:hover {
            background-color: var(--vscode-button-secondaryHoverBackground);
        }
        
        .copy-button {
            background-color: transparent;
            color: var(--vscode-textLink-foreground);
            border: 1px solid var(--vscode-textLink-foreground);
            padding: 6px 12px;
            font-size: 12px;
        }
        
        .copy-button:hover {
            background-color: var(--vscode-textLink-foreground);
            color: var(--vscode-editor-background);
        }
        
        .loading {
            text-align: center;
            padding: 40px;
            color: var(--vscode-descriptionForeground);
        }
        
        .empty-state {
            text-align: center;
            padding: 40px;
            color: var(--vscode-descriptionForeground);
        }
    </style>
</head>
<body>
    <div class="container">
        <h1>🧪 单元测试预览</h1>
        
        <div id="content" class="loading">
            加载中...
        </div>
        
        <div id="buttons" class="button-group" style="display: none;">
            <button class="btn-secondary" onclick="reject()">取消</button>
            <button class="btn-primary" onclick="accept()">接受并应用</button>
        </div>
    </div>

    <script>
        const vscode = acquireVsCodeApi();
        
        // 监听来自扩展的消息
        window.addEventListener('message', event => {
            const message = event.data;
            
            if (message.command === 'updatePreview') {
                renderPreview(message.data);
            }
        });
        
        function renderPreview(data) {
            const contentDiv = document.getElementById('content');
            const buttonsDiv = document.getElementById('buttons');
            
            if (!data) {
                contentDiv.innerHTML = '<div class="empty-state">没有可预览的内容</div>';
                return;
            }
            
            let gnSection = '';
            if (data.gnChanges) {
                gnSection = \`
                    <div class="section">
                        <div class="section-header">
                            📝 BUILD.gn 文件变更
                        </div>
                        <div class="section-content">
                            <div class="info-grid">
                                <span class="info-label">文件路径:</span>
                                <span class="info-value">\${data.gnChanges.filePath}</span>
                            </div>
                            <div class="diff-view">
                                <div class="diff-column">
                                    <h4>变更前</h4>
                                    <div class="code-block diff-removed">
                                        <pre>\${escapeHtml(data.gnChanges.oldContent)}</pre>
                                    </div>
                                </div>
                                <div class="diff-column">
                                    <h4>变更后</h4>
                                    <div class="code-block diff-added">
                                        <pre>\${escapeHtml(data.gnChanges.previewNewContent || data.gnChanges.newContent)}</pre>
                                    </div>
                                </div>
                            </div>
                            <div class="code-block" style="margin-top: 12px;">
                                <pre>\${escapeHtml(data.gnChanges.diff)}</pre>
                            </div>
                        </div>
                    </div>
                \`;
            }
            
            contentDiv.innerHTML = \`
                <div class="section">
                    <div class="section-header">
                        📊 基本信息
                    </div>
                    <div class="section-content">
                        <div class="info-grid">
                            <span class="info-label">函数名:</span>
                            <span class="info-value">\${escapeHtml(data.functionName)}</span>
                            
                            <span class="info-label">源文件:</span>
                            <span class="info-value">\${escapeHtml(data.sourceFilePath)}</span>
                            
                            <span class="info-label">测试文件:</span>
                            <span class="info-value">\${escapeHtml(data.testFilePath)}</span>
                        </div>
                    </div>
                </div>
                
                <div class="section">
                    <div class="section-header">
                        💡 生成说明
                    </div>
                    <div class="section-content">
                        <div class="explanation">
                            \${escapeHtml(data.explanation)}
                        </div>
                    </div>
                </div>
                
                <div class="section">
                    <div class="section-header">
                        <span>🧪 测试代码</span>
                        <button class="copy-button" onclick="copyCode()">复制代码</button>
                    </div>
                    <div class="section-content">
                        <div class="code-block">
                            <pre>\${escapeHtml(data.testCode)}</pre>
                        </div>
                    </div>
                </div>
                
                \${gnSection}
            \`;
            
            buttonsDiv.style.display = 'flex';
        }
        
        function escapeHtml(text) {
            const div = document.createElement('div');
            div.textContent = text;
            return div.innerHTML;
        }
        
        function accept() {
            vscode.postMessage({ command: 'accept' });
        }
        
        function reject() {
            vscode.postMessage({ command: 'reject' });
        }
        
        function copyCode() {
            vscode.postMessage({ 
                command: 'copyCode',
                code: document.querySelector('.code-block pre').textContent
            });
        }
    </script>
</body>
</html>`;
    }
}

